home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Languguage OS 2
/
Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO
/
language
/
ici
/
ici.cpi
/
alloc.h
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-27
|
5KB
|
153 lines
#ifndef ICI_ALLOC_H
#define ICI_ALLOC_H
/*
* If WHOALLOC is defined to be non-zero (i.e. 1) every allocation, records
* the C source file and line number it was made on and how much was allocated.
* It is them possible to print a summary, after running for a while, of what
* is still allocated. Mainly for finding leaks, but it can also be
* used for other debugging. Changing this requires total recompilation.
*/
#define WHOALLOC 0 /* Define to 1 to track who is using memory. */
/*
* Most allocated things will fit within 24 bytes, many of the rest within
* about 50. We keep our own lists of things of these sizes, and use the
* native system's mechanism for the remainder. Each items on our lists
* is also allocated directly from the system. Clearly some time and space
* advantage would be gained from allocating in larger chunks and then
* splitting up ourselves, but there are disadvantages too.
*
* Raw malloc's will end up being done of the sizes given here plus
* sizeof(int) plus futher alignment requirements. We allow these to be
* set from the configuration file so they can be fine tuned for a
* particular malloc. (eg. 64 may be a non-optimal size form some mallocs).
*/
#ifndef LIST1Z
#define LIST1Z 24
#endif
#define FEW_OBJS (LIST1Z / 4)
#ifndef LIST2Z
#define LIST2Z 56
#endif
#define FEW_MORE_OBJS (LIST2Z / 4)
/*
* To be sure that the area returned by ici_alloc is properly aligned
* we must add to the pointer originally returned by malloc a size
* which will maintain the worst case alignment requirement.
* Even though we only need one byte of space for our header.
*
* The following structure is used as an overlay to make sure we add
* the right amount to start user data at a good alignment position.
*/
typedef struct
{
#if !WHOALLOC
int ga_list; /* Which fast free list, 0 if none. */
#else
short ga_list;
short ga_who;
int ga_size;
#endif
union
{
char gau_data[1]; /* The first byte of user data when not free.*/
char *gau_next; /* Next free block when on fast free list. */
double gau_align; /* Only to force alignment. */
}
gau;
}
gahead_t;
/*
* The number of bytes between the prefix block header and the start
* of the user data. This is the overhead.
*/
#define GALLOC_HEADZ (((gahead_t *)NULL)->gau.gau_data \
-(char *)&((gahead_t *)NULL)->ga_list)
/*
* Return a pointer to the header, given the user pointer.
*/
#define gahead(p) ((gahead_t *)((char *)p - GALLOC_HEADZ))
/*
* Return the user pointer given a pointer to the header.
*/
#define gadata(p) (((gahead_t *)p)->gau.gau_data)
/*
* Given a size, which, if any, fast free list should it be on?
* Note that this will be a constant expression if z is a constant.
*/
#define galist(z) ((z) <= LIST1Z ? 1 : (z) <= LIST2Z ? 2 : 0)
/*
* Allocate memory as if by ici_alloc(). But if there is currently a block
* of suitable size on one of the fast free lists, just use that. If there
* isn't resort to the real ici_alloc() function.
*
* Every block allocated by ici_alloc() is prefixed by a header which contains
* an int. This int is 0 in general, but if the block is of an appropriate
* size for one of the fast free lists, it is a small integer index of that
* free list.
*/
#define zalloc(z) \
(ici_fflist[galist(z)] != NULL \
? ici_new_mem += (z), ici_fflist[galist(z)] \
= *(char **)(ici_fftmp = ici_fflist[galist(z)]), ici_fftmp \
: ici_alloc(z))
/*
* Free memory allocated with ici_alloc/zalloc. If it belongs on one of the
* fast free lists, just put it on that. Otherwise resort to the real function.
*/
#define zfree(p) \
if (gahead(p)->ga_list != 0) \
{ \
*(char **)(p) = ici_fflist[gahead(p)->ga_list]; \
ici_fflist[gahead(p)->ga_list] = (char *)(p); \
} \
else \
ici_free(p)
extern char *ici_fflist[]; /* The array of free lists heads. */
extern char *ici_fftmp; /* Temporary used in zalloc() above. */
extern long ici_old_mem; /* Num bytes in use after last collect. */
extern long ici_new_mem; /* Num bytes alloced since last collect. */
extern void ici_free(void *);
#if !WHOALLOC
extern void *ici_alloc(int);
#else
extern void *ici_alloc(int, char *, int);
#undef zalloc
#undef zfree
#define zalloc(z) ici_alloc((z), __FILE__, __LINE__)
#define zfree(p) ici_free(p)
#endif
#ifdef SMALL
/*
* If SMALL is defined we ignore all those macros and always use functions
* for allocation. No fast free lists are used. The address returned by
* malloc if the address of our objects. Incompatible with WHOALLOC.
* If your malloc() is even slightly slow this will significantly degrade
* performance.
*/
#undef GALLOC_HEADZ
#undef gahead
#undef gadata
#undef galist
#undef zalloc
#undef zfree
#define GALLOC_HEADZ 0
#define gahead(p) p
#define gadata(p) p
#define galist(z) 0
#define zalloc(z) ici_alloc(z)
#define zfree(p) ici_free(z)
#endif /* SMALL */
#endif /* ICI_ALLOC_H */